from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime, timedelta
from ..db import get_db
from .. import models, schemas
from ..security import get_current_user

router = APIRouter()

@router.post("/plan", response_model=List[schemas.ReviewTaskOut])
def create_review_plan(payload: schemas.ReviewPlanRequest, db: Session = Depends(get_db), current=Depends(get_current_user)):
    # Verify knowledge exists and belongs to user
    k = db.query(models.Knowledge).filter(models.Knowledge.id == payload.knowledge_id, models.Knowledge.owner_id == current.id).first()
    if not k:
        raise HTTPException(status_code=404, detail="Knowledge point not found")

    tasks = []
    now = datetime.utcnow()
    
    # Generate a unique plan_id
    import uuid
    plan_id = str(uuid.uuid4())
    
    dates = []
    if payload.plan_type == "ebbinghaus":
        # Ebbinghaus: 0 (today), 1, 2, 4, 7, 15, 30
        offsets = [0, 1, 2, 4, 7, 15, 30]
        dates = [now + timedelta(days=d) for d in offsets]
    elif payload.plan_type == "daily":
        # Generate for next 30 days including today
        dates = [now + timedelta(days=d) for d in range(0, 31)]
    elif payload.plan_type == "weekly":
        # Generate for next 12 weeks including today
        dates = [now + timedelta(weeks=w) for w in range(0, 13)]
    elif payload.plan_type == "monthly":
        # Generate for next 12 months including today
        dates = [now + timedelta(days=30*m) for m in range(0, 13)]
    elif payload.plan_type == "custom":
        if payload.custom_dates:
            dates = payload.custom_dates
        elif payload.custom_interval:
            # Generate 10 occurrences including today
            dates = [now + timedelta(days=payload.custom_interval * i) for i in range(0, 11)]
    
    for card_id in payload.card_ids:
        for d in dates:
            task = models.ReviewTask(
                knowledge_id=k.id,
                card_id=card_id,
                plan_type=payload.plan_type,
                plan_id=plan_id,
                due_date=d,
                owner_id=current.id,
                status="pending"
            )
            db.add(task)
            tasks.append(task)
    
    db.commit()
    for t in tasks:
        db.refresh(t)
    return tasks

@router.get("/", response_model=List[schemas.ReviewTaskOut])
def list_reviews(
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
    status: Optional[str] = None,
    db: Session = Depends(get_db),
    current=Depends(get_current_user)
):
    q = db.query(models.ReviewTask).filter(models.ReviewTask.owner_id == current.id)
    if start_date:
        q = q.filter(models.ReviewTask.due_date >= start_date)
    if end_date:
        q = q.filter(models.ReviewTask.due_date <= end_date)
    if status:
        q = q.filter(models.ReviewTask.status == status)
    
    return q.order_by(models.ReviewTask.due_date).all()

@router.get("", response_model=List[schemas.ReviewTaskOut])
def list_reviews_noslash(
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
    status: Optional[str] = None,
    db: Session = Depends(get_db),
    current=Depends(get_current_user)
):
    """Alias without trailing slash to avoid 307 redirect from /api/reviews to /api/reviews/.

    部署在某些反向代理或网关后时，307 重定向过程中可能丢失 Authorization 头，
    导致后续请求返回 401，从而触发前端全局 401 拦截器清空登录态并跳转登录页面。
    这里提供一个无尾斜杠的别名以保证 /api/reviews 可以被直接命中。
    """
    return list_reviews(start_date, end_date, status, db, current)

@router.delete("/{task_id}")
def delete_review_task(task_id: int, delete_plan: bool = False, db: Session = Depends(get_db), current=Depends(get_current_user)):
    t = db.query(models.ReviewTask).filter(models.ReviewTask.id == task_id, models.ReviewTask.owner_id == current.id).first()
    if not t:
        raise HTTPException(status_code=404, detail="Task not found")
    
    if delete_plan and t.plan_id:
        # Delete all future tasks with same plan_id
        db.query(models.ReviewTask).filter(
            models.ReviewTask.plan_id == t.plan_id,
            models.ReviewTask.owner_id == current.id,
            models.ReviewTask.status != 'done'
        ).delete()
        # Also delete the current task if not caught by above (e.g. if it was pending)
        # If the current task is done, we might want to keep it? 
        # But user said "delete this review plan", usually implies stopping it.
        # Let's just delete the current one too regardless of status if it's the trigger.
        # Actually, if we delete all future tasks, we should also delete the current one.
        # If the current one is already done, maybe we shouldn't delete it?
        # But the request is "delete this review plan".
        # Let's stick to deleting future pending tasks + current task.
        if t.status != 'done':
             db.delete(t)
    else:
        db.delete(t)
        
    db.commit()
    return {"ok": True}

@router.put("/{task_id}/status")
def update_task_status(task_id: int, status: str = Query(..., regex="^(pending|done)$"), db: Session = Depends(get_db), current=Depends(get_current_user)):
    t = db.query(models.ReviewTask).filter(models.ReviewTask.id == task_id, models.ReviewTask.owner_id == current.id).first()
    if not t:
        raise HTTPException(status_code=404, detail="Task not found")
    
    t.status = status
    if status == 'done':
        # Record log
        log = models.ReviewLog(
            knowledge_id=t.knowledge_id,
            card_id=t.card_id,
            owner_id=current.id
        )
        db.add(log)
        
    db.commit()
    return {"ok": True}
